using System;
using System.IO;
using System.Text;
using System.Threading;
using Oracle.ManagedDataAccess.Client;
using OracleInternal.Common;

namespace OracleInternal.NotificationServices
{
	internal class SenderThread : SupportClass.ThreadClass
	{
		private ONS oems;

		private NodeList nodeList;

		private Connection connection;

		private bool shutdown_Renamed_Field;

		private bool quiescent_Renamed_Field;

		private bool waitQ;

		private NotificationQueue q;

		private string id_Renamed_Field;

		private object lock_Renamed;

		protected internal SenderThread(NodeList list, Connection co)
		{
			if (ProviderConfig.m_bTraceLevelPrivate)
			{
				Trace.Write(OracleTraceLevel.Private, (OracleTraceTag)2097408, OracleTraceClassName.SenderThread, OracleTraceFuncName.ctor);
			}
			try
			{
				lock_Renamed = new object();
				shutdown_Renamed_Field = false;
				quiescent_Renamed_Field = false;
				waitQ = false;
				base.IsBackground = true;
				nodeList = list;
				oems = list.ons;
				connection = co;
				q = new NotificationQueue(oems);
				connection.ClientSender = this;
				id_Renamed_Field = new StringBuilder("SenderThread[" + connection.Id + "]").ToString();
			}
			catch (Exception ex)
			{
				OracleException.HandleError(OracleTraceLevel.Private, (OracleTraceTag)270532608, OracleTraceClassName.SenderThread, OracleTraceFuncName.ctor, ex);
				throw;
			}
			finally
			{
				if (ProviderConfig.m_bTraceLevelPrivate)
				{
					Trace.Write(OracleTraceLevel.Private, (OracleTraceTag)2097664, OracleTraceClassName.SenderThread, OracleTraceFuncName.ctor);
				}
			}
		}

		public override void Run()
		{
			if (ProviderConfig.m_bTraceLevelPrivate)
			{
				Trace.Write(OracleTraceLevel.Private, (OracleTraceTag)2097408, OracleTraceClassName.SenderThread, OracleTraceFuncName.Run);
			}
			try
			{
				runRemote();
			}
			catch (Exception ex)
			{
				OracleException.HandleError(OracleTraceLevel.Private, (OracleTraceTag)270532608, OracleTraceClassName.SenderThread, OracleTraceFuncName.Run, ex);
			}
			finally
			{
				if (ProviderConfig.m_bTraceLevelPrivate)
				{
					Trace.Write(OracleTraceLevel.Private, (OracleTraceTag)2097664, OracleTraceClassName.SenderThread, OracleTraceFuncName.Run);
				}
			}
		}

		private void runRemote()
		{
			if (ProviderConfig.m_bTraceLevelPrivate)
			{
				Trace.Write(OracleTraceLevel.Private, (OracleTraceTag)2097408, OracleTraceClassName.SenderThread, OracleTraceFuncName.runRemote);
			}
			try
			{
				while (!shutdown_Renamed_Field && !connection.shutdown)
				{
					if (quiescent_Renamed_Field)
					{
						while (quiescent_Renamed_Field && !shutdown_Renamed_Field)
						{
							lock (lock_Renamed)
							{
								try
								{
									Monitor.Wait(lock_Renamed, TimeSpan.FromMilliseconds(1000.0));
								}
								catch (Exception ex)
								{
									OracleException.HandleError(OracleTraceLevel.Private, (OracleTraceTag)270532608, OracleTraceClassName.SenderThread, OracleTraceFuncName.runRemote, ex);
								}
							}
						}
						continue;
					}
					Notification notification = null;
					SendElement sendElement = (SendElement)q.dequeue(blocking: false);
					if (sendElement == null)
					{
						notification = nodeList.getFirstPublished(this);
						if (notification == null)
						{
							lock (lock_Renamed)
							{
								waitQ = true;
							}
							sendElement = (SendElement)q.dequeue(blocking: true);
							lock (lock_Renamed)
							{
								waitQ = false;
							}
							if (sendElement == null || shutdown_Renamed_Field)
							{
								continue;
							}
						}
						else
						{
							sendElement = new SendElement(notification);
						}
					}
					ONSTcpClient clientSocket = connection.getClientSocket(block: false);
					if (clientSocket == null)
					{
						nodeList.clearPublishedSender(this);
						sendElement = null;
						notification = null;
						clientSocket = connection.getClientSocket(block: true);
						continue;
					}
					try
					{
						if (sendElement.e != null)
						{
							sendElement.e.send(new OutputBuffer(clientSocket.GetStream()), oems, connection);
							nodeList.removeFirstPublished(sendElement.e, this);
						}
						else if (sendElement.s != null)
						{
							sendElement.s.send(new OutputBuffer(clientSocket.GetStream()));
						}
					}
					catch (IOException ex2)
					{
						OracleException.HandleError(OracleTraceLevel.Private, (OracleTraceTag)270532608, OracleTraceClassName.SenderThread, OracleTraceFuncName.runRemote, ex2);
						nodeList.clearPublishedSender(this);
					}
				}
				nodeList.clearPublishedSender(this);
			}
			catch (Exception ex3)
			{
				OracleException.HandleError(OracleTraceLevel.Private, (OracleTraceTag)270532608, OracleTraceClassName.SenderThread, OracleTraceFuncName.runRemote, ex3);
				throw;
			}
			finally
			{
				if (ProviderConfig.m_bTraceLevelPrivate)
				{
					Trace.Write(OracleTraceLevel.Private, (OracleTraceTag)2097664, OracleTraceClassName.SenderThread, OracleTraceFuncName.runRemote);
				}
			}
		}

		protected internal virtual void send(SubscriptionNotification e)
		{
			if (ProviderConfig.m_bTraceLevelPrivate)
			{
				Trace.Write(OracleTraceLevel.Private, (OracleTraceTag)2097408, OracleTraceClassName.SenderThread, OracleTraceFuncName.send);
			}
			try
			{
				SendElement e2 = new SendElement(e);
				q.enqueue(e2);
			}
			catch (Exception ex)
			{
				OracleException.HandleError(OracleTraceLevel.Private, (OracleTraceTag)270532608, OracleTraceClassName.SenderThread, OracleTraceFuncName.send, ex);
				throw;
			}
			finally
			{
				if (ProviderConfig.m_bTraceLevelPrivate)
				{
					Trace.Write(OracleTraceLevel.Private, (OracleTraceTag)2097664, OracleTraceClassName.SenderThread, OracleTraceFuncName.send);
				}
			}
		}

		protected internal virtual void send(SubscriptionNotification e, int p)
		{
			if (ProviderConfig.m_bTraceLevelPrivate)
			{
				Trace.Write(OracleTraceLevel.Private, (OracleTraceTag)2097408, OracleTraceClassName.SenderThread, OracleTraceFuncName.send);
			}
			try
			{
				SendElement e2 = new SendElement(e);
				q.push(e2, p);
			}
			catch (Exception ex)
			{
				OracleException.HandleError(OracleTraceLevel.Private, (OracleTraceTag)270532608, OracleTraceClassName.SenderThread, OracleTraceFuncName.send, ex);
				throw;
			}
			finally
			{
				if (ProviderConfig.m_bTraceLevelPrivate)
				{
					Trace.Write(OracleTraceLevel.Private, (OracleTraceTag)2097664, OracleTraceClassName.SenderThread, OracleTraceFuncName.send);
				}
			}
		}

		protected internal virtual void shutdown()
		{
			if (ProviderConfig.m_bTraceLevelPrivate)
			{
				Trace.Write(OracleTraceLevel.Private, (OracleTraceTag)2097408, OracleTraceClassName.SenderThread, OracleTraceFuncName.shutdown);
			}
			try
			{
				shutdown_Renamed_Field = true;
				quiescent_Renamed_Field = false;
				try
				{
					q.drain_and_close(nodeList.shutdownTimeout);
				}
				catch (Exception ex)
				{
					OracleException.HandleError(OracleTraceLevel.Private, (OracleTraceTag)270532608, OracleTraceClassName.SenderThread, OracleTraceFuncName.shutdown, ex);
				}
				wakeThread();
			}
			catch (Exception ex2)
			{
				OracleException.HandleError(OracleTraceLevel.Private, (OracleTraceTag)270532608, OracleTraceClassName.SenderThread, OracleTraceFuncName.shutdown, ex2);
				throw;
			}
			finally
			{
				if (ProviderConfig.m_bTraceLevelPrivate)
				{
					Trace.Write(OracleTraceLevel.Private, (OracleTraceTag)2097664, OracleTraceClassName.SenderThread, OracleTraceFuncName.shutdown);
				}
			}
		}

		protected internal virtual void quiescent(bool status)
		{
			if (ProviderConfig.m_bTraceLevelPrivate)
			{
				Trace.Write(OracleTraceLevel.Private, (OracleTraceTag)2097408, OracleTraceClassName.SenderThread, OracleTraceFuncName.quiescent);
			}
			try
			{
				quiescent_Renamed_Field = status;
				if (!quiescent_Renamed_Field)
				{
					lock (lock_Renamed)
					{
						Monitor.Pulse(lock_Renamed);
					}
				}
			}
			catch (Exception ex)
			{
				OracleException.HandleError(OracleTraceLevel.Private, (OracleTraceTag)270532608, OracleTraceClassName.SenderThread, OracleTraceFuncName.quiescent, ex);
				throw;
			}
			finally
			{
				if (ProviderConfig.m_bTraceLevelPrivate)
				{
					Trace.Write(OracleTraceLevel.Private, (OracleTraceTag)2097664, OracleTraceClassName.SenderThread, OracleTraceFuncName.quiescent);
				}
			}
		}

		protected internal virtual void wakeThread()
		{
			if (ProviderConfig.m_bTraceLevelPrivate)
			{
				Trace.Write(OracleTraceLevel.Private, (OracleTraceTag)2097408, OracleTraceClassName.SenderThread, OracleTraceFuncName.wakeThread);
			}
			try
			{
				lock (lock_Renamed)
				{
					if (waitQ)
					{
						q.wake();
					}
					Monitor.Pulse(lock_Renamed);
				}
			}
			catch (Exception ex)
			{
				OracleException.HandleError(OracleTraceLevel.Private, (OracleTraceTag)270532608, OracleTraceClassName.SenderThread, OracleTraceFuncName.wakeThread, ex);
				throw;
			}
			finally
			{
				if (ProviderConfig.m_bTraceLevelPrivate)
				{
					Trace.Write(OracleTraceLevel.Private, (OracleTraceTag)2097664, OracleTraceClassName.SenderThread, OracleTraceFuncName.wakeThread);
				}
			}
		}

		protected internal virtual void flushSenderQueue()
		{
			if (ProviderConfig.m_bTraceLevelPrivate)
			{
				Trace.Write(OracleTraceLevel.Private, (OracleTraceTag)2097408, OracleTraceClassName.SenderThread, OracleTraceFuncName.flushSenderQueue);
			}
			try
			{
				while ((SendElement)q.dequeue(blocking: false) != null)
				{
				}
			}
			catch (Exception ex)
			{
				OracleException.HandleError(OracleTraceLevel.Private, (OracleTraceTag)270532608, OracleTraceClassName.SenderThread, OracleTraceFuncName.flushSenderQueue, ex);
				throw;
			}
			finally
			{
				if (ProviderConfig.m_bTraceLevelPrivate)
				{
					Trace.Write(OracleTraceLevel.Private, (OracleTraceTag)2097664, OracleTraceClassName.SenderThread, OracleTraceFuncName.flushSenderQueue);
				}
			}
		}
	}
}
